package com.yungu.swift.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Zerrion
 */
public class ValidateUtils {

    private static final int LENGTH = 11;

    /**
     * 中国地区的手机号码验证
     */
    private static final Pattern NUMBER_CHINAPHONELEGAL_PATTERN = Pattern.compile("^((13[0-9])|(15[^4])|(16[2,5,7])|(18[0,2,3,5-9])|(17[0-8])|(147)|(199)|(198)|(166))\\d{8}$");
    /**
     * 手机号码强验证和弱验证
     */
    private static final Pattern NUMBER_MOBILE_PATTERN = Pattern.compile("^(13[0-9]|14[5|7|9]|15[0|1|2|3|5|6|7|8|9]|16[6|2|5|7]|17[0|1|3|5|6|7|8]|18[0-9]|19[6|8|9])\\d{8}$");
    private static final Pattern WEAK_MOBILE = Pattern.compile("^\\d{11}$");
    /**
     * 身份证号码验证
     */
    private static final Pattern NUMBER_ID_CARD_PATTERN = Pattern.compile("(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)");

    /**
     * 中国电信号码格式验证 手机段： 133,153,180,181,189,177,1700,173,199,162
     **/
    private static final Pattern CHINA_TELECOM_PATTERN = Pattern.compile("(^1(33|53|62|77|73|99|8[019])\\d{8}$)|(^1700\\d{7}$)");

    /**
     * 中国联通号码格式验证 手机段：130,131,132,155,156,185,186,145,176,1709,167
     **/
    private static final Pattern CHINA_UNICOM_PATTERN = Pattern.compile("(^1(3[0-2]|4[5]|5[56]|67|7[6]|8[56])\\d{8}$)|(^1709\\d{7}$)");

    /**
     * 中国移动号码格式验证
     * 手机段：134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705,165
     **/
    private static final Pattern CHINA_MOBILE_PATTERN = Pattern.compile("(^1(3[4-9]|4[7]|5[0-27-9]|65|7[8]|8[2-478])\\d{8}$)|(^1705\\d{7}$)");


    private ValidateUtils() {

    }

    public static boolean validateMobile(String mobileNumber) {
        if (mobileNumber.length() != LENGTH) {
            return false;
        } else if ("142".equals(mobileNumber.substring(0, 3))) {
            return true;
        } else {
            Matcher matcher = NUMBER_MOBILE_PATTERN.matcher(mobileNumber);
            return matcher.matches();
        }
    }

    public static Boolean weakCheckMobile(String mobile) {
        if (mobile.length() != LENGTH) {
            return false;
        } else {
            Matcher matcher = WEAK_MOBILE.matcher(mobile);
            return matcher.matches();
        }
    }

    public static Boolean checkIdCard(String idCard) {
        if (idCard.length() != 18) {
            return false;
        } else {
            Matcher commonMatcher = NUMBER_ID_CARD_PATTERN.matcher(idCard);
            return commonMatcher.matches();
        }
    }

    public static Boolean isChinaPhoneLegal(String mobile) {
        Matcher m = NUMBER_CHINAPHONELEGAL_PATTERN.matcher(mobile);
        return m.matches();
    }

    /**
     * 判断传入的参数号码为哪家运营商
     *
     * @param mobile
     * @return 运营商名称
     */
    public static String checkMobile(String mobile) {
        if (mobile == null || mobile.trim().length() != 11) {
            throw new UnsupportedOperationException("Unknown Number");
        }
        if (CHINA_MOBILE_PATTERN.matcher(mobile).matches()) {
            return "1";
        }
        if (CHINA_UNICOM_PATTERN.matcher(mobile).matches()) {
            return "2";
        }
        if (CHINA_TELECOM_PATTERN.matcher(mobile).matches()) {
            return "3";
        }
        return "0";
    }


    /**
     * 校验银行卡卡号
     * 校验过程：
     * 1、从卡号最后一位数字开始，逆向将奇数位(1、3、5等等)相加。
     * 2、从卡号最后一位数字开始，逆向将偶数位数字，先乘以2（如果乘积为两位数，将个位十位数字相加，即将其减去9），再求和。
     * 3、将奇数位总和加上偶数位总和，结果应该可以被10整除。
     */
    public static boolean checkBankCard(String bankCard) {
        if (bankCard.length() < 15 || bankCard.length() > 19) {
            return false;
        }
        char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
        if (bit == 'N') {
            return false;
        }
        return bankCard.charAt(bankCard.length() - 1) == bit;
    }

    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     *
     * @param nonCheckCodeBankCard
     * @return
     */
    public static char getBankCardCheckCode(String nonCheckCodeBankCard) {
        if (nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
                || !nonCheckCodeBankCard.matches("\\d+")) {
            //如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeBankCard.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }

}
